package com.cnswhy.cloud.common.datasource.utils;

import lombok.var;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.validation.constraints.NotNull;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;

public class AESUtils {

    public static void main(String[] args) throws Exception {
        toolEncrypt("上海银行");
        toolDecrypt("Gz628u+TrGYvFEMHIg1dnA==");
        toolDecrypt("EzrGCTEt9jNzhZ2Am7PGJQ==");
    }

    public static Key keyFromBase64(String base64) {
        byte[] raw = Base64.getDecoder().decode(base64);
        return new SecretKeySpec(raw, "AES");
    }

    public static byte[] encrypt(Key key, byte[] content) throws Exception {
        return encrypt(key, content, "AES");
    }

    public static byte[] decrypt(Key key, byte[] content) throws Exception {
        return decrypt(key, content, "AES");
    }

    public static byte[] encrypt(Key key, byte[] content, String algorithm) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(content);
    }

    public static byte[] encrypt(Key key, byte[] content, String algorithm, AlgorithmParameterSpec algorithmParameterSpec) {

        try {
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, key, algorithmParameterSpec);
            return cipher.doFinal(content);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] decrypt(Key key, byte[] content, String algorithm) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(content);
    }

    public static byte[] decrypt(Key key, byte[] content, String algorithm, AlgorithmParameterSpec algorithmParameterSpec) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, key, algorithmParameterSpec);
        return cipher.doFinal(content);
    }

    public static void toolDecrypt(String src) throws Exception {
        Key aesKey;
        String keyBase64 = "zmLPmHKLor6SvWqrIXQvhmIWP66l3+wIhhwWElP9VYc=";
        byte[] raw = Base64.getDecoder().decode(keyBase64);
        aesKey = new SecretKeySpec(raw, "AES");
        AlgorithmParameterSpec aesIv = new IvParameterSpec("chenjiahandsome!".getBytes());
        System.out.println(
                new String(decrypt(aesKey, Base64Utils.decodeFromString(src),
                        "AES/CBC/PKCS5Padding", aesIv
                ), StandardCharsets.UTF_8)
        );
    }

    public static void toolEncrypt(@NotNull String src) throws Exception {
        Key aesKey;
        String keyBase64 = "zmLPmHKLor6SvWqrIXQvhmIWP66l3+wIhhwWElP9VYc=";
        byte[] raw = Base64.getDecoder().decode(keyBase64);
        aesKey = new SecretKeySpec(raw, "AES");
        AlgorithmParameterSpec aesIv = new IvParameterSpec("chenjiahandsome!".getBytes());
        var res = encrypt(aesKey,
                src.getBytes(StandardCharsets.UTF_8),
                "AES/CBC/PKCS5Padding",
                aesIv);
        System.out.println(Base64.getEncoder().encodeToString(res));
    }
}
